using Microsoft.Extensions.Logging;
using SeataNet.Core.Discovery;
using System.Security.Cryptography;
using System.Text;

namespace SeataNet.Core.LoadBalance
{
    /// <summary>
    /// 默认负载均衡器实现
    /// 支持多种负载均衡策略：轮询、随机、加权轮询、加权随机、一致性哈希
    /// </summary>
    public class DefaultLoadBalancer : ILoadBalancer
    {
        private readonly ILogger<DefaultLoadBalancer> _logger;
        private readonly LoadBalanceStrategy _strategy;
        private int _roundRobinIndex = 0;
        private readonly object _roundRobinLock = new object();
        private readonly Random _random = new Random();

        public DefaultLoadBalancer(
            ILogger<DefaultLoadBalancer> logger,
            LoadBalanceStrategy strategy = LoadBalanceStrategy.RoundRobin)
        {
            _logger = logger ?? throw new ArgumentNullException(nameof(logger));
            _strategy = strategy;

            _logger.LogInformation("Load balancer initialized with strategy: {Strategy}", _strategy);
        }

        /// <summary>
        /// 从服务实例列表中选择一个实例
        /// </summary>
        public ServiceInstance? Select(List<ServiceInstance> instances, string? context = null)
        {
            if (instances == null || instances.Count == 0)
            {
                _logger.LogWarning("No available service instances to select");
                return null;
            }

            // 过滤出健康且启用的实例
            var availableInstances = instances
                .Where(i => i.Healthy && i.Enabled)
                .ToList();

            if (availableInstances.Count == 0)
            {
                _logger.LogWarning("No healthy and enabled service instances available");
                return null;
            }

            // 如果只有一个实例，直接返回
            if (availableInstances.Count == 1)
            {
                return availableInstances[0];
            }

            // 根据策略选择实例
            ServiceInstance? selected = _strategy switch
            {
                LoadBalanceStrategy.RoundRobin => SelectByRoundRobin(availableInstances),
                LoadBalanceStrategy.Random => SelectByRandom(availableInstances),
                LoadBalanceStrategy.WeightedRoundRobin => SelectByWeightedRoundRobin(availableInstances),
                LoadBalanceStrategy.WeightedRandom => SelectByWeightedRandom(availableInstances),
                LoadBalanceStrategy.ConsistentHash => SelectByConsistentHash(availableInstances, context),
                LoadBalanceStrategy.LeastActive => SelectByLeastActive(availableInstances),
                _ => SelectByRoundRobin(availableInstances)
            };

            if (selected != null)
            {
                _logger.LogDebug("Selected instance: {ServiceName}@{Address} using strategy {Strategy}",
                    selected.ServiceName, selected.GetAddress(), _strategy);
            }

            return selected;
        }

        /// <summary>
        /// 获取负载均衡策略名称
        /// </summary>
        public string GetStrategyName()
        {
            return _strategy.ToString();
        }

        #region 负载均衡策略实现

        /// <summary>
        /// 轮询策略
        /// </summary>
        private ServiceInstance SelectByRoundRobin(List<ServiceInstance> instances)
        {
            lock (_roundRobinLock)
            {
                var index = _roundRobinIndex % instances.Count;
                _roundRobinIndex++;
                return instances[index];
            }
        }

        /// <summary>
        /// 随机策略
        /// </summary>
        private ServiceInstance SelectByRandom(List<ServiceInstance> instances)
        {
            var index = _random.Next(instances.Count);
            return instances[index];
        }

        /// <summary>
        /// 加权轮询策略
        /// </summary>
        private ServiceInstance SelectByWeightedRoundRobin(List<ServiceInstance> instances)
        {
            // 计算总权重
            var totalWeight = instances.Sum(i => i.Weight);

            if (totalWeight <= 0)
            {
                // 如果没有权重，使用普通轮询
                return SelectByRoundRobin(instances);
            }

            lock (_roundRobinLock)
            {
                var currentIndex = _roundRobinIndex % (int)totalWeight;
                _roundRobinIndex++;

                double accumulatedWeight = 0;
                foreach (var instance in instances)
                {
                    accumulatedWeight += instance.Weight;
                    if (currentIndex < accumulatedWeight)
                    {
                        return instance;
                    }
                }

                // 兜底返回第一个
                return instances[0];
            }
        }

        /// <summary>
        /// 加权随机策略
        /// </summary>
        private ServiceInstance SelectByWeightedRandom(List<ServiceInstance> instances)
        {
            // 计算总权重
            var totalWeight = instances.Sum(i => i.Weight);

            if (totalWeight <= 0)
            {
                // 如果没有权重，使用普通随机
                return SelectByRandom(instances);
            }

            // 生成一个[0, totalWeight)之间的随机数
            var randomValue = _random.NextDouble() * totalWeight;

            double accumulatedWeight = 0;
            foreach (var instance in instances)
            {
                accumulatedWeight += instance.Weight;
                if (randomValue < accumulatedWeight)
                {
                    return instance;
                }
            }

            // 兜底返回最后一个
            return instances[instances.Count - 1];
        }

        /// <summary>
        /// 一致性哈希策略
        /// </summary>
        private ServiceInstance SelectByConsistentHash(List<ServiceInstance> instances, string? context)
        {
            // 如果没有上下文信息，使用轮询
            if (string.IsNullOrEmpty(context))
            {
                _logger.LogWarning("No context provided for consistent hash, falling back to round robin");
                return SelectByRoundRobin(instances);
            }

            // 使用MD5计算哈希值
            using var md5 = MD5.Create();
            var hashBytes = md5.ComputeHash(Encoding.UTF8.GetBytes(context));
            var hashValue = BitConverter.ToUInt32(hashBytes, 0);

            // 简化的一致性哈希实现
            // 在实际生产中，应该使用虚拟节点和哈希环来实现更好的负载均衡
            var index = (int)(hashValue % (uint)instances.Count);
            return instances[index];
        }

        /// <summary>
        /// 最少活跃连接策略
        /// </summary>
        private ServiceInstance SelectByLeastActive(List<ServiceInstance> instances)
        {
            // 简化实现：选择权重最高的实例
            // 在实际生产中，应该维护每个实例的活跃连接数
            // 并选择活跃连接数最少的实例

            var maxWeight = instances.Max(i => i.Weight);
            var candidateInstances = instances.Where(i => Math.Abs(i.Weight - maxWeight) < 0.001).ToList();

            if (candidateInstances.Count == 1)
            {
                return candidateInstances[0];
            }

            // 如果有多个实例权重相同，随机选择一个
            return SelectByRandom(candidateInstances);
        }

        #endregion
    }

    /// <summary>
    /// 轮询负载均衡器
    /// </summary>
    public class RoundRobinLoadBalancer : DefaultLoadBalancer
    {
        public RoundRobinLoadBalancer(ILogger<DefaultLoadBalancer> logger)
            : base(logger, LoadBalanceStrategy.RoundRobin)
        {
        }
    }

    /// <summary>
    /// 随机负载均衡器
    /// </summary>
    public class RandomLoadBalancer : DefaultLoadBalancer
    {
        public RandomLoadBalancer(ILogger<DefaultLoadBalancer> logger)
            : base(logger, LoadBalanceStrategy.Random)
        {
        }
    }

    /// <summary>
    /// 加权轮询负载均衡器
    /// </summary>
    public class WeightedRoundRobinLoadBalancer : DefaultLoadBalancer
    {
        public WeightedRoundRobinLoadBalancer(ILogger<DefaultLoadBalancer> logger)
            : base(logger, LoadBalanceStrategy.WeightedRoundRobin)
        {
        }
    }

    /// <summary>
    /// 加权随机负载均衡器
    /// </summary>
    public class WeightedRandomLoadBalancer : DefaultLoadBalancer
    {
        public WeightedRandomLoadBalancer(ILogger<DefaultLoadBalancer> logger)
            : base(logger, LoadBalanceStrategy.WeightedRandom)
        {
        }
    }

    /// <summary>
    /// 一致性哈希负载均衡器
    /// </summary>
    public class ConsistentHashLoadBalancer : DefaultLoadBalancer
    {
        public ConsistentHashLoadBalancer(ILogger<DefaultLoadBalancer> logger)
            : base(logger, LoadBalanceStrategy.ConsistentHash)
        {
        }
    }

    /// <summary>
    /// 最少活跃连接负载均衡器
    /// </summary>
    public class LeastActiveLoadBalancer : DefaultLoadBalancer
    {
        public LeastActiveLoadBalancer(ILogger<DefaultLoadBalancer> logger)
            : base(logger, LoadBalanceStrategy.LeastActive)
        {
        }
    }
}
